package interpreter

type Function struct {
	*BaseFunction
	BodyNode         interface{}
	ArgNames         []string
	ShouldAutoReturn bool
}

func NewFunction(name string, bodyNode interface{}, argNames []string, shouldAutoReturn bool) *Function {
	temp := &Function{BaseFunction: NewBaseFunction(name)}
	temp.InitFunction(name, bodyNode, argNames, shouldAutoReturn)
	return temp
}

func (f *Function) InitFunction(name string, bodyNode interface{}, argNames []string, shouldAutoReturn bool) {
	f.BaseFunction.InitBaseFunction(name)
	f.BodyNode = bodyNode
	f.ArgNames = argNames
	f.ShouldAutoReturn = shouldAutoReturn
}

func (f *Function) Execute(args []interface{}) *RTResult {
	res := NewRTResult()

	interpreter_ := NewInterpreter()

	execCtx := f.GenerateNewContext("")

	res.Register(f.CheckAndPopulateArgs(f.ArgNames, args, execCtx))
	if res.ShouldReturn() != nil {
		return res
	}

	// 运行body内的节点
	value := res.Register(interpreter_.Visit(f.BodyNode, execCtx))
	if res.ShouldReturn() != nil && res.FuncReturnValue == nil {
		return res
	}

	var retValue interface{}
	var t1 interface{}
	if f.ShouldAutoReturn {
		t1 = value
	} else {
		t1 = nil
	}
	t2 := res.FuncReturnValue
	t3 := Null

	if t1 != nil {
		retValue = t1
		if t2 != nil {
			retValue = t2
			if t3 != nil {
				retValue = t3
			}
		}
	}

	return res.Success(retValue)
}

// 拷贝
func (f *Function) Copy() *Function {
	copy_ := NewFunction(f.Name, f.BodyNode, f.ArgNames, f.ShouldAutoReturn)
	copy_.SetContext(f.Context)
	copy_.SetPos(f.PosStart, f.PosEnd)
	return copy_
}
